<template>
  <div style="width: 100%; height: 100%">
    <div style="position: relative; width: 100%; height: 100%">
      <video v-if="key" :key="key" ref="videoRef" muted style="width: 100%; height: 100%"></video>
      <loading v-if="loading" style="position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto" />
    </div>
  </div>
</template>

<script>
import { h } from 'vue';
import flvJs from '../mpegts.js';
import Loading from '../loading.js';
import message from 'ant-design-vue/es/message/index.js';
import Modal from 'ant-design-vue/es/modal/index.js';

console.log(flvJs);

function getKey() {
  return (Number(String(Math.random()).slice(2)) + Date.now()).toString(36);
}

function exec(handle, onError) {
  try {
    handle();
  } catch (error) {
    typeof onError === 'function' && onError(error);
  }
}

function flvNotSupportNotice() {
  if (!window.flvNotSupportWaring) {
    window.flvNotSupportWaring = Modal.warning({
      title: h('span', { style: { color: '#faad14' } }, '提醒'),
      content: h(
        'span',
        { style: { fontSize: '18px', color: '#ffffff' } },
        '当前浏览器不支持实时视频播放器,请尝试升级最新浏览器 !'
      ),
      maskClosable: false,
      closable: false,
      keyboard: false,
      centered: true,
      okText: '知道了',
      onOk: () => {
        delete window.flvNotSupportWaring;
      },
    });
  }
}

export default {
  name: 'FlvPlayer',
  components: { Loading },
  props: {
    streamUrl: { type: String, default: undefined },
    autoplay: { type: Boolean, default: true },
    options: { type: Object, default: undefined },
  },
  data() {
    return { key: '', loading: false };
  },
  mounted() {
    this.$watch(
      () => this.streamUrl,
      function () {
        this.init();
      },
      { immediate: true }
    );
  },
  unmounted() {
    document.body.removeEventListener('click', this.play);
    this.destroyPlayer();
  },
  methods: {
    init() {
      this.loading = true;
      if (!this.streamUrl) {
        return;
      }
      this.checkSupported(async () => {
        this.destroyPlayer();
        await this.createPlayer();
        this.player.retry = async () => {
          message.error('播放出错了,正在尝试重新播放,请稍后~', 3);
          this.destroyPlayer();
          this.key = getKey();
          await this.createPlayer();
          this.player.retry = () => {
            this.destroyPlayer();
            setTimeout(() => {
              message.error('播放出错了,切换其他监控试试!', 5);
              this.$emit('close');
            }, 5000);
          };
        };
      });
    },
    checkSupported(then) {
      if (flvJs.isSupported()) {
        return then();
      }
      flvNotSupportNotice();
    },
    createPlayer() {
      return new Promise((resolve) => {
        this.key = getKey();
        this.$nextTick(() => {
          let opt = { type: 'flv', isLive: true, hasVideo: true, hasAudio: false };
          opt = Object.assign(opt, this.options, { url: this.streamUrl });
          this.player = flvJs.createPlayer(opt);
          this.player.on(flvJs.Events.ERROR, (error) => {
            this.handleError(error);
          });
          this.player.attachMediaElement(this.$refs.videoRef);
          // console.log(this.player);
          if (this.autoplay === true) {
            /* 尝试播放, 但一般情况下会报这个错:
             * play() failed because the user didn't interact with the document first.
             * */
            this.play(() => {
              /* 播放失败的处理  */
              document.body.addEventListener('click', this.play);
            });
          }
          resolve();
        });
      });
    },
    handleError(error) {
      // console.log(error);
      switch (error) {
        case flvJs.ErrorTypes.NETWORK_ERROR:
          message.error('网络出错了,请稍后尝试!', 5);
          throw new Error(error);
        case flvJs.ErrorTypes.OTHER_ERROR:
          message.error('播放出错了,请稍后尝试!', 5);
          throw new Error(error);
        case flvJs.ErrorTypes.MEDIA_ERROR:
          this.retry();
          break;
      }
    },
    destroyPlayer() {
      exec(() => {
        this.player.pause();
        this.player.unload();
        this.player.destroy();
      });
    },
    retry() {
      exec(() => {
        this.player.retry();
      });
    },
    play(onError) {
      exec(() => {
        this.player.unload();
        this.player.load();
        this.player.play();
        setTimeout(() => {
          this.loading = false;
        }, 1000);
      }, onError);
    },
    pause() {
      exec(() => {
        this.player.pause();
      });
    },
    stop() {
      exec(() => {
        this.player.unload();
      });
    },
  },
};
</script>
